package geppetto.cat.corpus;

import geppetto.cat.alignments.AlignmentStats;
import geppetto.cat.alignments.AlignmentsSet;
import geppetto.cat.common.Pair;
import gnu.trove.TIntArrayList;

import java.awt.Container;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;




public class BilingualCorpusStats {

	public static void computeWordFreqs(BilingualCorpus test,
			BilingualCorpus train) {
		int sourceCommonWords = 0, sourceRareWords = 0, sourceUnknowWords = 0;
		int foreignCommonWords = 0, foreignRareWords = 0, foreignUnknowWords = 0;
		int sourceCommonTypes = 0, sourceRareTypes = 0, sourceUnknowTypes = 0;
		int foreignCommonTypes = 0, foreignRareTypes = 0, foreignUnknowTypes = 0;
		for (String sourceType : test._vocabNamesSource) {
			int testSourceTypePos = test._vocabSource.get(sourceType);
			if (train._vocabSource.containsKey(sourceType)) {
				int trainSourceTypePos = train._vocabSource.get(sourceType);
				if (train.sourceRareWord(trainSourceTypePos, 20)) {
					sourceRareTypes++;
					sourceRareWords += test._sourceWordsCounts.get(testSourceTypePos);
				} else {
					sourceCommonTypes++;
					sourceCommonWords += test._sourceWordsCounts.get(testSourceTypePos);
				}
			} else {
				sourceUnknowTypes++;
				sourceUnknowWords += test._sourceWordsCounts.get(testSourceTypePos);
			}

		}

		for (String foreignType : test._vocabNamesForeign) {
			int testForeignTypePos = test._vocabForeign.get(foreignType);
			if (train._vocabForeign.containsKey(foreignType)) {
				int trainForeignTypePos = train._vocabForeign.get(foreignType);
				if (train.foreignRareWord(trainForeignTypePos, 20)) {
					foreignRareTypes++;
					foreignRareWords += test._foreignWordsCounts
							.get(testForeignTypePos);
				} else {
					foreignCommonTypes++;
					foreignCommonWords += test._foreignWordsCounts
							.get(testForeignTypePos);
				}
			} else {
				foreignUnknowTypes++;
				foreignUnknowWords += test._foreignWordsCounts
						.get(testForeignTypePos);
			}
		}
		int sourceTotalTypes = sourceCommonTypes + sourceRareTypes
				+ sourceUnknowTypes;
		int foreignTotalTypes = foreignCommonTypes + foreignRareTypes
				+ foreignUnknowTypes;
		int sourceTotalWords = sourceCommonWords + sourceRareWords
				+ sourceUnknowWords;
		int foreignTotalWords = foreignCommonWords + foreignRareWords
				+ foreignUnknowWords;
		System.out.println("Source Words: Total " + sourceTotalWords
				+ " common " + (sourceCommonWords * 100.0 / sourceTotalWords)
				+ " rare " + (sourceRareWords * 100.0 / sourceTotalWords)
				+ " Unknown " + (sourceUnknowWords * 100.0 / sourceTotalWords));
		System.out.println("Source Types: Total " + sourceTotalTypes
				+ " common " + (sourceCommonTypes * 100.0 / sourceTotalTypes)
				+ " rare " + (sourceRareTypes * 100.0 / sourceTotalTypes)
				+ " Unknown " + (sourceUnknowTypes * 100.0 / sourceTotalTypes));
		System.out.println("Foreign Words: Total " + foreignTotalWords
				+ " common " + (foreignCommonWords * 100.0 / foreignTotalWords)
				+ " rare " + (foreignRareWords * 100.0 / foreignTotalWords)
				+ " Unknown "
				+ (foreignUnknowWords * 100.0 / foreignTotalWords));
		System.out.println("Foreign Types: Total " + foreignTotalTypes
				+ " common " + (foreignCommonTypes * 100.0 / foreignTotalTypes)
				+ " rare " + (foreignRareTypes * 100.0 / foreignTotalTypes)
				+ " Unknown "
				+ (foreignUnknowTypes * 100.0 / foreignTotalTypes));
	}

	// Output test sentences
	public static void sentenceStats(BilingualCorpus test) {
		System.out.println("Source "
				+ " max "
				+ test.getMaxSourceLen()
				+ " avg "
				+ (test.getTotalSourceWords() * 1.0 / test
						.getNumberOfTrainingSentences()));
		System.out.println("Foreign "
				+ " max "
				+ test.getMaxForeignLen()
				+ " avg "
				+ (test.getTotalForeignWords() * 1.0 / test
						.getNumberOfTrainingSentences()));

	}

	/**
	 * Computes the statitics of a Translation Test set against the used test.
	 * Note that the test set should not be included in the training set
	 * 
	 * @throws IOException
	 * 
	 */
	public static void statsOfTestSet(String trainingCorpusParams,
			String testCorpusParams) throws IOException {
		BilingualCorpus train = BilingualCorpus.getCorpusFromFileDescription(
				trainingCorpusParams, Integer.MAX_VALUE);
		BilingualCorpus test = BilingualCorpus.getCorpusFromFileDescription(
				testCorpusParams, Integer.MAX_VALUE);
		computeWordFreqs(test, train);
		sentenceStats(test);
		System.out.print("Sentence stats on training");
		sentenceStats(train);

	}

	static class sortWords implements Comparator{

		public int compare(Object arg0, Object arg1) {
			Pair<Integer,Integer> p1 = (Pair<Integer,Integer>)arg0;
			Pair<Integer,Integer> p2 = (Pair<Integer,Integer>)arg1;
			if(p1.second() < p2.second()){
				return 1;
			}else{
				return -1;
			}
		}
	}
	
	public static ArrayList<Pair>[] getCorpusCounts(BilingualCorpus corpus){
		ArrayList<Pair>[] result = new ArrayList[2];
		result[0] = new ArrayList<Pair>();
		result[1] = new ArrayList<Pair>();
		int nrForeingWords = corpus.getForeignSize();
		int nrSourceWords = corpus.getSourceSize();
		for(int i = 0; i < nrForeingWords; i++){
			result[0].add(new Pair(i,corpus._foreignWordsCounts.get(i)));		
		}
		Collections.sort(result[0], new sortWords());
		for(int i = 0; i < nrSourceWords; i++){
			result[1].add(new Pair(i,corpus._sourceWordsCounts.get(i)));		
		}
		Collections.sort(result[1], new sortWords());
		
		int foreingSum  =0;
		for(int i = 0; i < nrForeingWords; i++){
			foreingSum += (Integer) result[0].get(i).second();
		}
		
		int sourceSum = 0;
		for(int i = 0; i < nrSourceWords; i++){
			sourceSum += (Integer) result[1].get(i).second();
		}
		
		ArrayList<Pair> comulativeTarget = new  ArrayList<Pair>();
		int runninSum = 0;
		for(int i = 0; i < nrForeingWords; i++){
			int value = (Integer)result[0].get(i).second();
			runninSum+=value;
			comulativeTarget.add(new Pair(result[0].get(i).first(),1.0*runninSum/foreingSum));
		}
		System.out.println("Foreing Comulative");
		
		int usedWords = 0;
		for(int i = 0; i < nrForeingWords; i++){
			if((Double)comulativeTarget.get(i).second() < 0.8){
				usedWords++;
				System.out.println(comulativeTarget.get(i) + "("+(Integer) result[0].get(i).second()
						+"-"+corpus.getForeignString((Integer)result[0].get(i).first())+ ")");
			}
		}
		System.out.println("Total of words"+usedWords + " out of " + corpus.getForeignSize());
		
		
		return result;
	}
	
	public static void main(String[] args) throws IOException {
		BilingualCorpus corpus = BilingualCorpus.getCorpusFromFileDescription(args[0],Integer.parseInt(args[1]),40);
		sentenceStats(corpus);
		AlignmentsSet set = corpus.getGold();
		AlignmentStats.printPhrases(set,false,true);
	}

}
